`include "../define.svh"
module Adder_FP_top (
    input clk,
    input sys_rst_n,
    input valid1,
    input valid2,
    input [1:0]data_type,  
    input [`DATA_SIZE-1:0]a_in,
    input [`DATA_SIZE-1:0]b_in,
    output [`DATA_SIZE-1:0]float_o,
    output adder_valid //连接下一级加法器的valid端
);
//valid信号输出
        wire en;
        assign en=valid1&&valid2;   //加法器使能

         // 流水线 valid 信号延迟（4级）
    reg valid_pipeline;

    always @(posedge clk or negedge sys_rst_n) begin
        if (!sys_rst_n) begin
            valid_pipeline <= 1'b0;
        end else begin
            valid_pipeline <= en;
        end
    end

    // 最终 valid 信号：特殊情况或普通运算有效
    assign adder_valid = valid_pipeline;
//************************************************//
    wire s1,s2;
    wire [7:0]e1,e2;
    wire [23:0]m1,m2;

    wire s_out,spec_valid;
    wire [7:0]e_spec;
    wire [22:0]m_spec;
    wire [27:0]m_sum;
    wire co;

    wire [26:0]m1_align,m2_align;
    wire [7:0]e_align;
    wire [7:0]e_align_reg;

    wire [8:0]e_norm;
    wire [27:0]m_norm;
    wire sign_out;
    wire [5:0]data_shift;
    
    wire [8:0]e_rnd_out;
    wire [23:0]m_rnd_o;


    wire [22:0]m_spec_r3;
    wire s_spec_r3;
    wire [7:0]e_spec_r3;
    wire spec_valid_r3;


    wire [7:0]e_final;
    wire [22:0]m_final;

/*     reg sign_out_reg1;
    reg sign_out_reg2; */
    
/*     always @(posedge clk or negedge sys_rst_n) begin
        if (!sys_rst_n) begin
            sign_out_reg1 <= 1'b0;
            sign_out_reg2 <= 1'b0;
        end else begin
            sign_out_reg1 <= sign_out;
            sign_out_reg2 <= sign_out_reg1;
        end
    end */

    unpack unpack_add_inst
(
    .unpack_en(en),     //使能信号
    .data_type(data_type),
    .data_in(a_in),
    .weight_in(b_in),
     .s1_reg(s1),
     .s2_reg(s2),
     .e1_reg(e1),
     .e2_reg(e2),
     .m1_reg(m1),
     .m2_reg(m2)
);

    add_special_case  spec_inst(
    .data_type(data_type),  //2'b00:INT4,2'b01:INT8,2'b10:FP16,2'b11:FP32
    .e1(e1),
    .e2(e2),
    .s1(s1),
    .s2(s2),
    .m1(m1),
    .m2(m2),
    .e_out(e_spec),
    .m_out(m_spec),
    .output_sign(s_out),//符号位输出
    .spec_valid(spec_valid)  //valid信号，给下一级模块
);

/*     add_pipeline add_pipeline_inst(
    .clk(clk),
    .sys_rst_n(sys_rst_n),
    .spec_valid(spec_valid),
    .e_spec(e_spec),
    .m_spec(m_spec),
    .s_spec(s_out),
    .m_spec_r3(m_spec_r3),
    .e_spec_r3(e_spec_r3),  
    .s_spec_r3(s_spec_r3),
    .spec_valid_r3(spec_valid_r3)
); */

    mant_add  u_mant_add(
    //.clk(clk),
    //.sys_rst_n(sys_rst_n),
    .m1(m1_align),         // 输入尾数1（含隐含位）
    .m2(m2_align),         // 输入尾数2（含隐含位）
    //.e_align(e_align),
    .s1(s1),                // 符号位1
    .s2(s2),                // 符号位2
    .sign_out(sign_out),    //符号位输出
    .sum(m_sum)    // 尾数和（[26]符号位, [25:0]数值
    //.e_align_reg(e_align_reg)
);

    add_align align_inst(
    .exp1(e1), 
    .exp2(e2),        // 输入指数（假设为FP32，8位）
    .s1(s1),
    .s2(s2),
    .mantissa1(m1),
    .mantissa2(m2), // 输入尾数（隐藏位已添加）
    .larger_exp(e_align),      // 对齐后的指数（取较大值）
    .aligned_mantissa_s(m1_align), // 对齐后的主尾数（保留24位与符号位）
    .mantissa_out_s(m2_align)     //另一个尾数（未执行操作）
    //.sticky_bits_reg(sticky)      // 被移出的低位（用于舍入）
);

    lzd_28bit #(
    .WIDTH(28)
) lzd_inst(
    .data(m_sum),
    .count(data_shift)
);

    norm_add  norm_inst(
/*     .clk(clk),
    .sys_rst_n(sys_rst_n), */
    .e_in(e_align),
    .m_sum(m_sum),
    .shift(data_shift),
    .data_type(data_type),
    .e_norm_stage1(e_norm),
    .m_norm_stage1(m_norm)
);

    round_add round_inst(
/*     .clk(clk),
    .sys_rst_n(sys_rst_n), */
    .e_norm(e_norm),
    .m_norm(m_norm),
    .data_type(data_type),
    .e_out(e_rnd_out),
    .m_rnd_o(m_rnd_o)
    //.underflow()
);
/*     denormal_round u_denormal_round(
    .clk(clk),
    .mant(m_rnd_o),
    .e_norm(e_rnd_out),
    .data_type(data_type),
    .mant_out_reg(m_denorm),
    .exp_out(e_denorm),
    .underflow(underflow)
); */

    overflow_add overflow_inst(
    .data_type(data_type),
    .m_norm_i(m_rnd_o),
    .e_norm_i(e_rnd_out),
    .e_out_final(e_final),
    .m_out_final(m_final)
);

    adder_out out_inst(
    .clk(clk),
    .sys_rst_n(sys_rst_n),
    .data_type(data_type),
    .spec_valid(spec_valid),
    .e_spec_in(e_spec),              //来自special模块的指数输出
    .m_spec_in(m_spec),             //来自special的尾数输出
    .s_spec(s_out),
    .m_final(m_final),           //普通运算得到的结果
    .e_final(e_final),            //普通运算得到的结果
    .s_final(sign_out),
    .product_o(float_o)
);
endmodule